package com.ch4;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;

/**
 * @author woldier
 * @version 1.0
 * @description 消费者模式
 * @date 2023/5/6 15:22
 **/

@Slf4j(topic = "c.Demo09")
public class Demo09 {
    public static void main(String[] args) {
        MessageQueue<Message> messageQueue = new MessageQueue<>(2);
        for (int i = 0; i < 3; i++) {
            int id = i;
            new Thread(()->{
                messageQueue.put(new Message(id,"ssss"+id));
            },"线程"+i).start();
        }

        new Thread(()->{

            while (true){
                Message message = messageQueue.get();
            }
        },"消费者").start();
    }

}

@Slf4j(topic = "c.MessageQueue")
final class MessageQueue<T> {
    private final LinkedList<T> linkedList = new LinkedList<>();
    private int size;

    public MessageQueue(int size) {
        if (size <= 0) size = 10;
        this.size = size;
    }
    /**
    *
    * description 放入数据
    *
    * @param message  消息
    * @return void
    * @author: woldier
    * @date: 2023/5/6 15:34
    */

    /**
    *
    * description 取出数据
    *
    * @param message  消息
    * @return void
    * @author: woldier
    * @date: 2023/5/6 15:39
    */
    public void put(T message) {
        synchronized (linkedList) {
            //判断是否容量满
            while (linkedList.size() == size){
                log.debug("队列满,需要等待");
                try {
                    linkedList.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            log.debug("放入数据");
            //放入list
            linkedList.add(message);
            //唤醒可能get阻塞的线程
            linkedList.notifyAll();
        }
    }

    public T get(){
        synchronized (linkedList){
            //判断队列是否为空
            while(linkedList.size()==0){
                log.debug("队列空了,需要等待");
                try {
                    linkedList.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            //取出一条数据
            log.debug("消费一条数据");
            T t = linkedList.removeLast();
            linkedList.notifyAll();
            return t;
        }
    }

}

@Data
@AllArgsConstructor
@Slf4j(topic = "c.Message")
class Message {
    private long id;
    private String msg;
}
